/*
 * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*
 * NOTICE: Currently, it only supports i.mx6q usb charger detect
 */

#ifndef __IMXUSB_CHARGER_H
#define __IMXUSB_CHARGER_H

#define HW_ANADIG_REG_3P0	(0x00000120)
#define HW_ANADIG_REG_3P0_SET	(0x00000124)
#define HW_ANADIG_REG_3P0_CLR	(0x00000128)
#define HW_ANADIG_REG_3P0_TOG	(0x0000012c)
#define BM_ANADIG_REG_3P0_ENABLE_ILIMIT 0x00000004
#define BM_ANADIG_REG_3P0_ENABLE_LINREG 0x00000001

#define HW_ANADIG_USB1_VBUS_DETECT	(0x000001a0)
#define HW_ANADIG_USB1_VBUS_DETECT_SET	(0x000001a4)
#define HW_ANADIG_USB1_VBUS_DETECT_CLR	(0x000001a8)
#define HW_ANADIG_USB1_VBUS_DETECT_TOG	(0x000001ac)

#define BM_ANADIG_USB1_VBUS_DETECT_EN_CHARGER_RESISTOR 0x80000000
#define BP_ANADIG_USB1_VBUS_DETECT_RSVD2      28
#define BM_ANADIG_USB1_VBUS_DETECT_RSVD2 0x70000000
#define BF_ANADIG_USB1_VBUS_DETECT_RSVD2(v)  \
	(((v) << 28) & BM_ANADIG_USB1_VBUS_DETECT_RSVD2)
#define BM_ANADIG_USB1_VBUS_DETECT_CHARGE_VBUS 0x08000000
#define BM_ANADIG_USB1_VBUS_DETECT_DISCHARGE_VBUS 0x04000000
#define BP_ANADIG_USB1_VBUS_DETECT_RSVD1      21
#define BM_ANADIG_USB1_VBUS_DETECT_RSVD1 0x03E00000
#define BF_ANADIG_USB1_VBUS_DETECT_RSVD1(v)  \
	(((v) << 21) & BM_ANADIG_USB1_VBUS_DETECT_RSVD1)
#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_PWRUP_CMPS 0x00100000
#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_5VDETECT 0x00080000
#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_TO_B 0x00040000
#define BP_ANADIG_USB1_VBUS_DETECT_RSVD0      8
#define BM_ANADIG_USB1_VBUS_DETECT_RSVD0 0x0003FF00
#define BF_ANADIG_USB1_VBUS_DETECT_RSVD0(v)  \
	(((v) << 8) & BM_ANADIG_USB1_VBUS_DETECT_RSVD0)
#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_OVERRIDE 0x00000080
#define BM_ANADIG_USB1_VBUS_DETECT_AVALID_OVERRIDE 0x00000040
#define BM_ANADIG_USB1_VBUS_DETECT_BVALID_OVERRIDE 0x00000020
#define BM_ANADIG_USB1_VBUS_DETECT_SESSEND_OVERRIDE 0x00000010
#define BM_ANADIG_USB1_VBUS_DETECT_VBUS_OVERRIDE_EN 0x00000008
#define BP_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH      0
#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH 0x00000007
#define BF_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH(v)  \
	(((v) << 0) & BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH)

#define HW_ANADIG_USB1_CHRG_DETECT	(0x000001b0)
#define HW_ANADIG_USB1_CHRG_DETECT_SET	(0x000001b4)
#define HW_ANADIG_USB1_CHRG_DETECT_CLR	(0x000001b8)
#define HW_ANADIG_USB1_CHRG_DETECT_TOG	(0x000001bc)

#define BP_ANADIG_USB1_CHRG_DETECT_RSVD2      24
#define BM_ANADIG_USB1_CHRG_DETECT_RSVD2 0xFF000000
#define BF_ANADIG_USB1_CHRG_DETECT_RSVD2(v) \
	(((v) << 24) & BM_ANADIG_USB1_CHRG_DETECT_RSVD2)
#define BM_ANADIG_USB1_CHRG_DETECT_BGR_BIAS 0x00800000
#define BP_ANADIG_USB1_CHRG_DETECT_RSVD1      21
#define BM_ANADIG_USB1_CHRG_DETECT_RSVD1 0x00600000
#define BF_ANADIG_USB1_CHRG_DETECT_RSVD1(v)  \
	(((v) << 21) & BM_ANADIG_USB1_CHRG_DETECT_RSVD1)
#define BM_ANADIG_USB1_CHRG_DETECT_EN_B 0x00100000
#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B 0x00080000
#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT 0x00040000
#define BP_ANADIG_USB1_CHRG_DETECT_RSVD0      1
#define BM_ANADIG_USB1_CHRG_DETECT_RSVD0 0x0003FFFE
#define BF_ANADIG_USB1_CHRG_DETECT_RSVD0(v)  \
	(((v) << 1) & BM_ANADIG_USB1_CHRG_DETECT_RSVD0)
#define BM_ANADIG_USB1_CHRG_DETECT_FORCE_DETECT 0x00000001

#define HW_ANADIG_USB1_VBUS_DET_STAT	(0x000001c0)
#define HW_ANADIG_USB1_VBUS_DET_STAT_SET	(0x000001c4)
#define HW_ANADIG_USB1_VBUS_DET_STAT_CLR	(0x000001c8)
#define HW_ANADIG_USB1_VBUS_DET_STAT_TOG	(0x000001cc)

#define BP_ANADIG_USB1_VBUS_DET_STAT_RSVD0      4
#define BM_ANADIG_USB1_VBUS_DET_STAT_RSVD0 0xFFFFFFF0
#define BF_ANADIG_USB1_VBUS_DET_STAT_RSVD0(v) \
	(((v) << 4) & BM_ANADIG_USB1_VBUS_DET_STAT_RSVD0)
#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID 0x00000008
#define BM_ANADIG_USB1_VBUS_DET_STAT_AVALID 0x00000004
#define BM_ANADIG_USB1_VBUS_DET_STAT_BVALID 0x00000002
#define BM_ANADIG_USB1_VBUS_DET_STAT_SESSEND 0x00000001

#define HW_ANADIG_USB1_CHRG_DET_STAT	(0x000001d0)
#define HW_ANADIG_USB1_CHRG_DET_STAT_SET	(0x000001d4)
#define HW_ANADIG_USB1_CHRG_DET_STAT_CLR	(0x000001d8)
#define HW_ANADIG_USB1_CHRG_DET_STAT_TOG	(0x000001dc)

#define BP_ANADIG_USB1_CHRG_DET_STAT_RSVD0      4
#define BM_ANADIG_USB1_CHRG_DET_STAT_RSVD0 0xFFFFFFF0
#define BF_ANADIG_USB1_CHRG_DET_STAT_RSVD0(v) \
	(((v) << 4) & BM_ANADIG_USB1_CHRG_DET_STAT_RSVD0)
#define BM_ANADIG_USB1_CHRG_DET_STAT_DP_STATE 0x00000008
#define BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE 0x00000004
#define BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED 0x00000002
#define BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT 0x00000001

#define HW_ANADIG_USB1_LOOPBACK	(0x000001e0)
#define HW_ANADIG_USB1_LOOPBACK_SET	(0x000001e4)
#define HW_ANADIG_USB1_LOOPBACK_CLR	(0x000001e8)
#define HW_ANADIG_USB1_LOOPBACK_TOG	(0x000001ec)

#define BP_ANADIG_USB1_LOOPBACK_RSVD0      9
#define BM_ANADIG_USB1_LOOPBACK_RSVD0 0xFFFFFE00
#define BF_ANADIG_USB1_LOOPBACK_RSVD0(v) \
	(((v) << 9) & BM_ANADIG_USB1_LOOPBACK_RSVD0)
#define BM_ANADIG_USB1_LOOPBACK_UTMO_DIG_TST1 0x00000100
#define BM_ANADIG_USB1_LOOPBACK_UTMO_DIG_TST0 0x00000080
#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_HIZ 0x00000040
#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN 0x00000020
#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_LS_MODE 0x00000010
#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_HS_MODE 0x00000008
#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 0x00000004
#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST0 0x00000002
#define BM_ANADIG_USB1_LOOPBACK_UTMI_TESTSTART 0x00000001

#define HW_ANADIG_USB1_MISC	(0x000001f0)
#define HW_ANADIG_USB1_MISC_SET	(0x000001f4)
#define HW_ANADIG_USB1_MISC_CLR	(0x000001f8)
#define HW_ANADIG_USB1_MISC_TOG	(0x000001fc)

#define BM_ANADIG_USB1_MISC_RSVD1 0x80000000
#define BM_ANADIG_USB1_MISC_EN_CLK_UTMI 0x40000000
#define BM_ANADIG_USB1_MISC_RX_VPIN_FS 0x20000000
#define BM_ANADIG_USB1_MISC_RX_VMIN_FS 0x10000000
#define BM_ANADIG_USB1_MISC_RX_RXD_FS 0x08000000
#define BM_ANADIG_USB1_MISC_RX_SQUELCH 0x04000000
#define BM_ANADIG_USB1_MISC_RX_DISCON_DET 0x02000000
#define BM_ANADIG_USB1_MISC_RX_HS_DATA 0x01000000
#define BP_ANADIG_USB1_MISC_RSVD0      2
#define BM_ANADIG_USB1_MISC_RSVD0 0x00FFFFFC
#define BF_ANADIG_USB1_MISC_RSVD0(v)  \
	(((v) << 2) & BM_ANADIG_USB1_MISC_RSVD0)
#define BM_ANADIG_USB1_MISC_EN_DEGLITCH 0x00000002
#define BM_ANADIG_USB1_MISC_HS_USE_EXTERNAL_R 0x00000001

#include <linux/power_supply.h>
enum battery_charging_spec {
	BATTERY_CHARGING_SPEC_NONE = 0,
	BATTERY_CHARGING_SPEC_UNKNOWN,
	BATTERY_CHARGING_SPEC_1_0,
	BATTERY_CHARGING_SPEC_1_1,
	BATTERY_CHARGING_SPEC_1_2,
};

struct usb_charger {
	void __iomem 		*charger_base_addr; /* Get from MSL if exists */
	struct device		*dev; /* udc supplies */
	/* charger detect can be enabled/disabled by kernel config */
	bool 			enable;
	struct power_supply	psy;
	struct work_struct	work;
	struct mutex		lock;

	/* Compliant with Battery Charging Specification version (if any) */
	enum battery_charging_spec	bc;

	/* properties */
	unsigned		present:1;
	unsigned		online:1;
	unsigned		max_current;
	/* pull up/down dp during the charger detect, udc supplies */
	void 	(*dp_pullup)(bool);
	int	(*connect)(struct usb_charger *charger);
	int	(*disconnect)(struct usb_charger *charger);
	int	(*set_power)(struct usb_charger *charger, unsigned mA);

	int	(*detect)(struct usb_charger *charger);
};

static char *usb_charger_supplied_to[] = {
	"imx_usb_charger",
};

static enum power_supply_property power_props[] = {
	POWER_SUPPLY_PROP_PRESENT,	/* Charger detected */
	POWER_SUPPLY_PROP_ONLINE,	/* VBUS online */
	POWER_SUPPLY_PROP_CURRENT_MAX,	/* Maximum current in mA */
};

#endif /* __IMXUSB_CHARGER_H */
